package com.haixiaoke.saas.order.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.aliyun.oss.model.OSSObject;
import com.haixiaoke.saas.common.config.WeChatConfig;
import com.haixiaoke.saas.common.constant.OrderConstants;
import com.haixiaoke.saas.common.core.domain.AjaxResult;
import com.haixiaoke.saas.common.core.redis.RedisCache;
import com.haixiaoke.saas.common.enums.OrderStateEnum;
import com.haixiaoke.saas.common.exception.ServiceException;
import com.haixiaoke.saas.common.oss.OssService;
import com.haixiaoke.saas.common.utils.DateUtils;
import com.haixiaoke.saas.common.weChat.domain.RefundOrder;
import com.haixiaoke.saas.common.weChat.service.WeChatService;
import com.haixiaoke.saas.department.domain.WechatAccount;
import com.haixiaoke.saas.department.service.IWechatAccountService;
import com.haixiaoke.saas.order.domain.*;
import com.haixiaoke.saas.order.mapper.OrderAuditRecordMapper;
import com.haixiaoke.saas.order.service.*;
import com.haixiaoke.saas.order.state.server.IOrderStateServerRole;
import com.haixiaoke.saas.order.state.server.OrderStateServerRole;
import com.haixiaoke.saas.user.domain.BizUserBusiness;
import com.haixiaoke.saas.user.service.IBizUserBusinessService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

import static com.haixiaoke.saas.system.framework.security.util.SecurityUtils.getLoginUser;

/**
 * 订单审核记录Service业务层处理
 *
 * @author qixi
 * @date 2024-04-02
 */
@Service
public class OrderAuditRecordServiceImpl implements IOrderAuditRecordService {
    @Autowired
    private OrderAuditRecordMapper orderAuditRecordMapper;
    @Autowired
    private IOrderService orderService;
    @Autowired
    private IOrderChargeItemService orderChargeItemService;
    @Autowired
    private IOrderHousingExpensesService orderHousingExpensesService;
    @Autowired
    private IOrderRefundItemService orderRefundItemService;
    @Autowired
    private IOrderRefundDetailsService orderRefundDetailsService;
    @Autowired
    private WeChatService weChatService;
    @Autowired
    private IWechatAccountService wechatAccountService;
    @Autowired
    private WeChatConfig weChatConfig;
    @Autowired
    private OssService ossService;
    @Autowired
    private IOrderStateRecordService orderStateRecordService;
    @Autowired
    private IBizUserBusinessService bizUserBusinessService;
    @Autowired
    private RedisCache redisCache;

    /**
     * 查询订单审核记录
     *
     * @param recordId 订单审核记录主键
     * @return 订单审核记录
     */
    @Override
    public OrderAuditRecord selectOrderAuditRecordByRecordId(Long recordId) {
        OrderAuditRecord orderAuditRecord = orderAuditRecordMapper.selectOrderAuditRecordByRecordId(recordId);
        String orderContent = orderAuditRecord.getOrderContent();
        orderAuditRecord.setOrder(JSONUtil.toBean(orderContent, Order.class));
        return orderAuditRecord;
    }

    /**
     * 查询订单审核记录列表
     *
     * @param orderAuditRecord 订单审核记录
     * @return 订单审核记录
     */
    @Override
    public List<OrderAuditRecord> selectOrderAuditRecordList(OrderAuditRecord orderAuditRecord) {
        List<OrderAuditRecord> orderAuditRecords = orderAuditRecordMapper.selectOrderAuditRecordList(orderAuditRecord);
        orderAuditRecords.forEach(x ->
                x.setOrder(JSONUtil.toBean(x.getOrderContent(), Order.class)));
        return orderAuditRecords;
    }

    /**
     * 新增订单审核记录
     *
     * @param orderAuditRecord 订单审核记录
     * @return 结果
     */
    @Override
    public int insertOrderAuditRecord(OrderAuditRecord orderAuditRecord) {
        orderAuditRecord.setCreateTime(DateUtils.getNowDate());
        return orderAuditRecordMapper.insertOrderAuditRecord(orderAuditRecord);
    }

    /**
     * 修改订单审核记录
     *
     * @param orderAuditRecord 订单审核记录
     * @return 结果
     */
    @Override
    public int updateOrderAuditRecord(OrderAuditRecord orderAuditRecord) {
        return orderAuditRecordMapper.updateOrderAuditRecord(orderAuditRecord);
    }

    /**
     * 审核订单
     *
     * @param orderAuditRecord
     * @return
     */
    @Override
    public int reviewOrder(OrderAuditRecord orderAuditRecord) {
        Long recordId = orderAuditRecord.getRecordId();
        OrderAuditRecord record = orderAuditRecordMapper.selectOrderAuditRecordByRecordId(recordId);
        String auditRecordState = record.getAuditRecordState();
        if (!OrderConstants.AUDIT_RECORD_STATE_AUDIT.equals(auditRecordState)) {
            throw new ServiceException("当前订单已经审核，无法进行审核操作");
        }
        orderAuditRecord.setUpdateTime(DateUtils.getNowDate());
        String orderContent = record.getOrderContent();
        Order order = JSON.parseObject(orderContent, Order.class);

        IOrderStateServerRole orderStateServerRole = new OrderStateServerRole(order);

        if (orderAuditRecord.getAuditRecordState().equals(OrderConstants.AUDIT_RECORD_STATE_PASS)) {
            orderStateServerRole.approved();
        }

        if (orderAuditRecord.getAuditRecordState().equals(OrderConstants.AUDIT_RECORD_STATE_NOT)) {
            orderStateServerRole.disagree();
        }

        orderAuditRecord.setUpdateBy(getLoginUser().getUsername());
        return orderAuditRecordMapper.updateOrderAuditRecord(orderAuditRecord);
    }

    /**
     * 批量删除订单审核记录
     *
     * @param recordIds 需要删除的订单审核记录主键
     * @return 结果
     */
    @Override
    public int deleteOrderAuditRecordByRecordIds(Long[] recordIds) {
        return orderAuditRecordMapper.deleteOrderAuditRecordByRecordIds(recordIds);
    }

    /**
     * 删除订单审核记录信息
     *
     * @param recordId 订单审核记录主键
     * @return 结果
     */
    @Override
    public int deleteOrderAuditRecordByRecordId(Long recordId) {
        return orderAuditRecordMapper.deleteOrderAuditRecordByRecordId(recordId);
    }

    @Override
    public OrderAuditRecord selectOrderAuditRecordByOrderId(String orderId) {
        return orderAuditRecordMapper.selectOrderAuditRecordByOrderId(orderId);

    }

    @Override
    public OrderAuditRecord selectOrderAuditRecordByOrderIdAndAuditRecordState(String orderId, String recordState) {
        return orderAuditRecordMapper.selectOrderAuditRecordByOrderIdAndAuditRecordState(orderId, recordState);
    }

    @Override
    public List<OrderAuditRecord> selectAuditcanCelReservationList(OrderAuditRecord orderAuditRecord) {
        return orderAuditRecordMapper.selectAuditcanCelReservationList(orderAuditRecord);
    }

    @Override
    public OrderAuditRecord selectOrderCancelReservationGetInfoById(Long recordId) {
        OrderAuditRecord orderAuditRecord = orderAuditRecordMapper.selectOrderAuditRecordByRecordId(recordId);
        if (ObjectUtil.isNotEmpty(orderAuditRecord)) {
            Order order = orderService.selectOrderById(orderAuditRecord.getOrderId());
//            OrderRefundItem refundItem = orderRefundItemService.selectOrderRefundItemByOrderIdAndRefundType(orderId, OrderConstants.REFUND_TYPE_HOUSE_PRICE);
            /*OrderRefundItem refundItem = orderRefundItemService.selectOrderRefundItemByOrderIdAndRefundTypeAndRecordId(orderId,
                                                                                                            OrderConstants.REFUND_TYPE_HOUSE_PRICE,
                                                                                                            orderAuditRecord.getRecordId());*/
            OrderStateRecord orderStateRecord = orderStateRecordService.selectOrderStateRecordByOrderIdAndState(orderAuditRecord.getOrderId(), OrderStateEnum.ORDER_STATE_UNSUBSCRIBING.getValue());
            List<OrderChargeItem> chargeItemList = orderChargeItemService.selectOrderChargeItemByOrderId(order.getOrderId());
            List<OrderHousingExpenses> housingExpensesList = orderHousingExpensesService.selectHousingExpensesByOrderId(order.getOrderId(), false);
            List<OrderRefundItem> refundItemList = orderRefundItemService.selectOrderRefundItemByOrderIdAndRecordId(order.getOrderId(),orderAuditRecord.getRecordId());
            List<OrderRefundDetails> refundDetailsList = orderRefundDetailsService.selectOrderRefundDetailsByOrderIdAndRecordId(order.getOrderId(),orderAuditRecord.getRecordId());
            OrderPriceVO orderPriceVO = orderService.packageOrderPriceVO(chargeItemList, housingExpensesList, refundItemList, refundDetailsList, null);
            order.setOrderPriceVO(orderPriceVO);
            orderAuditRecord.setOrder(order);
            orderAuditRecord.setOrderChargeItemList(chargeItemList);
            orderAuditRecord.setOrderHousingExpensesList(housingExpensesList);
            orderAuditRecord.setOrderRefundItemList(refundItemList);
            orderAuditRecord.setOrderRefundDetailsList(refundDetailsList);
            orderAuditRecord.setOrderStateRecord(orderStateRecord);
//            orderAuditRecord.setOrderRefundItem(refundItem);

            if (ObjectUtil.isNotEmpty(orderAuditRecord.getOperatorId())) {
                BizUserBusiness userBusiness = bizUserBusinessService.selectBizUserBusinessByUserId(orderAuditRecord.getOperatorId(), orderAuditRecord.getTenantId());
                if (ObjectUtil.isNotEmpty(userBusiness)) {
                    orderAuditRecord.setOperatorName(userBusiness.getUserName());
                }
            }
        }
        return orderAuditRecord;
    }

    @Override
    @Transactional
    public AjaxResult reviewCancelReservationOrder(OrderAuditRecord auditRecord) {
        Date nowDate = DateUtils.getNowDate();
        //房费退款金额
        auditRecord.setUpdateTime(nowDate);
        auditRecord.setAuditTime(nowDate);
        int result = orderAuditRecordMapper.updateOrderAuditRecord(auditRecord);
        //删除redis的key，防止触发缓存过期回调时间
        redisCache.deleteObject(OrderConstants.REDIS_AUDIT_ORDER_KEY + auditRecord.getRecordId());
        BigDecimal housePrice = BigDecimal.ZERO;
        //填写退款金额
        Order order = orderService.selectOrderById(auditRecord.getOrderId());
        if (StrUtil.equals(OrderConstants.AUDIT_RECORD_STATE_PASS,auditRecord.getAuditRecordState())) {
            BigDecimal totalPrice = BigDecimal.ZERO;
            //房费每日详情修改，及统计退款的金额总金额
            List<OrderRefundDetails> refundDetailsList = orderRefundDetailsService.selectOrderRefundDetailsByOrderIdAndRecordId(auditRecord.getOrderId(),auditRecord.getRecordId());
            //不需要退的房费详情id集合
            List<Long> refundDetailsIds = auditRecord.getRefundDetailsIds();
            if (CollectionUtil.isNotEmpty(refundDetailsIds) && !refundDetailsIds.isEmpty()) {
                for (OrderRefundDetails refundDetails : refundDetailsList) {
                    //退款每日详情包含指定退款的，则修改状态为退款成功
                    if (refundDetailsIds.contains(refundDetails.getId())) {
                        refundDetails.setRefundState(OrderConstants.REFUND_STATE_NO);
                    } else {
                        refundDetails.setRefundState(OrderConstants.REFUND_STATE_YES);
                        housePrice = housePrice.add(refundDetails.getRefundPrice());
                    }

                }
            } else {
                housePrice = refundDetailsList.stream().map(OrderRefundDetails::getRefundPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
                refundDetailsList.forEach(x -> x.setRefundState(OrderConstants.REFUND_STATE_YES));
            }
            orderRefundDetailsService.updateBatchOrderRefundDetails(refundDetailsList);
            List<OrderRefundItem> refundItemList = orderRefundItemService.selectOrderRefundItemByOrderIdAndRecordId(auditRecord.getOrderId(),auditRecord.getRecordId());
            for (OrderRefundItem refundItem : refundItemList) {
                if (StrUtil.equals(OrderConstants.REFUND_TYPE_HOUSE_PRICE, refundItem.getRefundType())) {
                    refundItem.setItemSum(housePrice);
                } else if (StrUtil.equals(OrderConstants.REFUND_TYPE_CASH_PLEDGE, refundItem.getRefundType())) {
                    totalPrice = housePrice.add(refundItem.getItemSum());
                }
            }
            BigDecimal finalTotalPrice = totalPrice;
            refundItemList.forEach(x -> x.setTotalPrice(finalTotalPrice));
            orderRefundItemService.updateBatchOrderRefundItem(refundItemList);

            order.setRefundAmount(totalPrice);
            orderService.updateOrder(order);
            if (result > 0) {
                WechatAccount account = wechatAccountService.selectWechatAccountByTenantId(auditRecord.getTenantId());
                if (ObjectUtil.isEmpty(account)) {
                    throw new ServiceException("商户号数据异常");
                }
                RefundOrder refundOrder = new RefundOrder();
                refundOrder.setAppId(weChatConfig.getAppId());
                refundOrder.setMchId(account.getAccountId());
                refundOrder.setMchApiKey(account.getAccountApiKey());
                OSSObject object = ossService.getObject(account.getAccountCertificate());
                byte[] bytes = ossService.parseObject(object);
                if (bytes == null) {
                    throw new ServiceException("商户证书获取异常");
                }
                refundOrder.setMchCertificate(bytes);

                refundOrder.setOutTradeNo(auditRecord.getOrderId());
                refundOrder.setOutRefundNo(auditRecord.getOrderId());
//                int refund = totalPrice.multiply(BigDecimal.valueOf(100)).intValue();
                refundOrder.setTotalFee(1/*refund*/);
                refundOrder.setRefundFee(1/*refund*/);
                refundOrder.setNotifyUrl(weChatConfig.getCancelReservationCallBackUrl());
                return weChatService.refundOrder(refundOrder);
            }
        } else if (StrUtil.equals(OrderConstants.AUDIT_RECORD_STATE_NOT,auditRecord.getAuditRecordState())){
            //orderRefundItemService.deleteOrderRefundItemByOrderId(order.getOrderId());
            //orderRefundDetailsService.deleteOrderRefundDetailsByOrderId(order.getOrderId());
            //审核不通过,订单状态变回待入住
            IOrderStateServerRole orderStateServerRole = new OrderStateServerRole(order);
            orderStateServerRole.unsubscribeFailureStayCheckIn(auditRecord.getRemark());
        }

        return result >0 ? AjaxResult.success():AjaxResult.error();
    }

    @Override
    public int apartmentCountOrderState(Long userId) {
        return orderAuditRecordMapper.apartmentCountOrderState(userId);
    }

    @Override
    public List<OrderAuditRecord> selectOrderAuditRecordByOrderIds(List<String> orderIds) {
        if (CollectionUtil.isEmpty(orderIds)) {
            return null;
        }
        return orderAuditRecordMapper.selectOrderAuditRecordByOrderIds(orderIds);
    }
}
